home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / zcpp_jae.zip / CPP4.C < prev    next >
C/C++ Source or Header  |  1990-07-06  |  18KB  |  619 lines

  1. /*
  2.  
  3.  
  4.  Copyright (C) 1990 Texas Instruments Incorporated.
  5.  
  6.  Permission is granted to any individual or institution to use, copy, modify,
  7.  and distribute this software, provided that this complete copyright and
  8.  permission notice is maintained, intact, in all copies and supporting
  9.  documentation.
  10.  
  11.  Texas Instruments Incorporated provides this software "as is" without
  12.  express or implied warranty.
  13.  
  14.  
  15.  *                C P P 4 . C
  16.  *        M a c r o  D e f i n i t i o n s
  17.  *
  18.  * Edit History
  19.  * 31-Aug-84    MM    USENET net.sources release
  20.  * 04-Oct-84    MM    __LINE__ and __FILE__ must call ungetstring()
  21.  *            so they work correctly with token concatenation.
  22.  *            Added string formal recognition.
  23.  * 25-Oct-84    MM    "Short-circuit" evaluate #if's so that we
  24.  *            don't print unnecessary error messages for
  25.  *            #if !defined(FOO) && FOO != 0 && 10 / FOO ...
  26.  * 31-Oct-84    ado/MM    Added token concatenation
  27.  *  6-Nov-84    MM    Split off eval stuff
  28.  * 21-Oct-85    RMS    Rename `token' to `tokenbuf'.
  29.  *            In doundef, don't complain if arg already not defined.
  30.  * 20-Apr-90    MJF     Changed redefining of defined variable to a warning
  31.  * 18-May-90    MBN     Conditional compilation for COOL to get "clean" cpp
  32.  */
  33.  
  34. #include    <stdio.h>
  35. #include    <ctype.h>
  36. #include    "cppdef.h"
  37. #include    "cpp.h"
  38. /*
  39.  * parm[], parmp, and parlist[] are used to store #define() argument
  40.  * lists.  nargs contains the actual number of parameters stored.
  41.  */
  42. static char    parm[NPARMWORK + 1];    /* define param work buffer     */
  43. static char    *parmp;            /* Free space in parm        */
  44. static char    *parlist[LASTPARM];    /* -> start of each parameter    */
  45. static int    nargs;            /* Parameters for this macro    */
  46.  
  47. dodefine()
  48. /*
  49.  * Called from control when a #define is scanned.  This module
  50.  * parses formal parameters and the replacement string.  When
  51.  * the formal parameter name is encountered in the replacement
  52.  * string, it is replaced by a character in the range 128 to
  53.  * 128+NPARAM (this allows up to 32 parameters within the
  54.  * Dec Multinational range).  If cpp is ported to an EBCDIC
  55.  * machine, you will have to make other arrangements.
  56.  *
  57.  * There is some special case code to distinguish
  58.  *    #define foo    bar
  59.  * from    #define foo()    bar
  60.  *
  61.  * Also, we make sure that
  62.  *    #define    foo    foo
  63.  * expands to "foo" but doesn't put cpp into an infinite loop.
  64.  *
  65.  * A warning message is printed if you redefine a symbol to a
  66.  * different text.  I.e,
  67.  *    #define    foo    123
  68.  *    #define foo    123
  69.  * is ok, but
  70.  *    #define foo    123
  71.  *    #define    foo    +123
  72.  * is not.
  73.  *
  74.  * The following subroutines are called from define():
  75.  * checkparm    called when a token is scanned.  It checks through the
  76.  *        array of formal parameters.  If a match is found, the
  77.  *        token is replaced by a control byte which will be used
  78.  *        to locate the parameter when the macro is expanded.
  79.  * textput    puts a string in the macro work area (parm[]), updating
  80.  *        parmp to point to the first free byte in parm[].
  81.  *        textput() tests for work buffer overflow.
  82.  * charput    puts a single character in the macro work area (parm[])
  83.  *        in a manner analogous to textput().
  84.  */
  85. {
  86.     register int        c;
  87.     register DEFBUF        *dp;        /* -> new definition    */
  88.     int            isredefine;    /* TRUE if redefined    */
  89.     char            *old;        /* Remember redefined    */
  90.     extern int        save();        /* Save char in work[]    */
  91.  
  92.     if (type[(c = skipws())] != LET)
  93.         goto bad_define;
  94.     isredefine = FALSE;            /* Set if redefining    */
  95.     if ((dp = lookid(c)) == NULL)        /* If not known now    */
  96.         dp = defendel(tokenbuf, FALSE);    /* Save the name    */
  97.     else {                    /* It's known:        */
  98.         isredefine = TRUE;            /* Remember this fact    */
  99.         old = dp->repl;            /* Remember replacement    */
  100.         dp->repl = NULL;            /* No replacement now    */
  101.     }
  102.     parlist[0] = parmp = parm;        /* Setup parm buffer    */
  103.     if ((c = get()) == '(') {        /* With arguments?    */
  104.         nargs = 0;                /* Init formals counter    */
  105.         do {                /* Collect formal parms    */
  106.         if (nargs >= LASTPARM)
  107.             cfatal("Too many arguments for macro", NULLST);
  108.         else if ((c = skipws()) == ')')
  109.             break;            /* Got them all        */
  110.         else if (type[c] != LET)    /* Bad formal syntax    */
  111.             goto bad_define;
  112.         scanid(c);            /* Get the formal param    */
  113.         parlist[nargs++] = parmp;    /* Save its start    */
  114.         textput(tokenbuf);        /* Save text in parm[]    */
  115.         } while ((c = skipws()) == ',');    /* Get another argument    */
  116.         if (c != ')')            /* Must end at )    */
  117.         goto bad_define;
  118.         c = ' ';                /* Will skip to body    */
  119.     }
  120.     else {
  121.         /*
  122.          * DEF_NOARGS is needed to distinguish between
  123.          * "#define foo" and "#define foo()".
  124.          */
  125.         nargs = DEF_NOARGS;            /* No () parameters    */
  126.     }
  127.     if (type[c] == SPA)            /* At whitespace?    */
  128.         c = skipws();            /* Not any more.    */
  129.     workp = work;                /* Replacement put here    */
  130.     inmacro = TRUE;                /* Keep \<newline> now    */
  131.     while (c != EOF_CHAR && c != '\n') {    /* Compile macro body    */
  132. #if OK_CONCAT
  133.         if (c == '#') {            /* Token concatenation?    */
  134.           if((c = get()) != '#') {
  135.         save('#');            /* Lone #, just save it. */
  136.         if(type[c] == LET) {
  137.           if (checkparm(c, dp))     /* Single # next to parm */
  138.             workp[-2] = MAC_PARM + PAR_MAC;/* Mark next parameter */
  139.           c = get();}  
  140.             continue;}
  141.           while (workp > work && type[(unsigned char)workp[-1]] == SPA)
  142.         --workp;            /* Erase leading spaces    */
  143.           save(TOK_SEP);            /* Stuff a delimiter    */
  144.           c = skipws();            /* Eat whitespace    */
  145.           continue;
  146.         }
  147. #endif    /*  OK_CONCAT  */
  148.         switch (type[c]) {
  149.         case LET:
  150.         checkparm(c, dp);        /* Might be a formal    */
  151.         break;
  152.  
  153.         case DIG:                /* Number in mac. body    */
  154.         case DOT:                /* Maybe a float number    */
  155.         scannumber(c, save);        /* Scan it off        */
  156.         break;
  157.  
  158.         case QUO:                /* String in mac. body    */
  159. #if STRING_FORMAL
  160.         stparmscan(c, dp);        /* Do string magic    */
  161. #else
  162.         scanstring(c, save);
  163. #endif
  164.         break;
  165.  
  166.         case BSH:                /* Backslash        */
  167.         save('\\');
  168.         if ((c = get()) == '\n')
  169.             wrongline = TRUE;
  170.         save(c);
  171.         break;
  172.  
  173.         case SPA:                /* Absorb whitespace    */
  174.         /*
  175.          * Note: the "end of comment" marker is passed on
  176.          * to allow comments to separate tokens.
  177.          */
  178.         if (workp[-1] == ' ')        /* Absorb multiple    */
  179.             break;            /* spaces        */
  180.         else if (c == '\t')
  181.             c = ' ';            /* Normalize tabs    */
  182.         /* Fall through to store character            */
  183.         default:                /* Other character    */
  184.         save(c);
  185.         break;
  186.         }
  187.         c = get();
  188.     }
  189.     inmacro = FALSE;            /* Stop newline hack    */
  190.     unget();                /* For control check    */
  191.     if (workp > work && workp[-1] == ' ')    /* Drop trailing blank    */
  192.         workp--;
  193.     *workp = EOS;                /* Terminate work    */
  194.     dp->repl = savestring(work);        /* Save the string    */
  195.     dp->nargs = nargs;            /* Save arg count    */
  196. #if DEBUG
  197.     if (debug)
  198.         dumpadef("macro definition", dp);
  199. #endif
  200.     if (isredefine) {            /* Error if redefined    */
  201.         if ((old != NULL && dp->repl != NULL && !streq(old, dp->repl))
  202.          || (old == NULL && dp->repl != NULL)
  203.          || (old != NULL && dp->repl == NULL)) {
  204.         cwarn("Redefining defined variable \"%s\"", dp->name);
  205.         }
  206.         if (old != NULL)            /* We don't need the    */
  207.         free(old);            /* old definition now.    */
  208.     }     
  209.     return;
  210.  
  211. bad_define:
  212.     cerror("#define syntax error", NULLST);
  213.     inmacro = FALSE;            /* Stop <newline> hack    */
  214. }
  215.  
  216. int
  217. checkparm(c, dp)
  218. register int    c;
  219. DEFBUF        *dp;
  220. /*
  221.  * Replace this param if it's defined, returning TRUE.
  222.  * Note that the macro name is a possible replacement token.
  223.  * We stuff DEF_MAGIC in front of the token
  224.  * which is treated as a LETTER by the token scanner and eaten by
  225.  * the output routine.  This prevents the macro expander from
  226.  * looping if someone writes "#define foo foo".
  227.  */
  228. {
  229.     register int        i;
  230.     register char        *cp;
  231.  
  232.     scanid(c);                /* Get parm to tokenbuf */
  233.     for (i = 0; i < nargs; i++) {        /* For each argument    */
  234.         if (streq(parlist[i], tokenbuf)) {    /* If it's known    */
  235.         save(i + MAC_PARM);            /* Save a magic cookie    */
  236.         return(TRUE);            /* And exit the search    */
  237.         }
  238.     }
  239.     if (streq(dp->name, tokenbuf))        /* Macro name in body?    */
  240.         save(DEF_MAGIC);            /* Save magic marker    */
  241.     for (cp = tokenbuf; *cp != EOS;)    /* And save        */
  242.         save(*cp++);            /* The token itself    */
  243.     return(FALSE);
  244. }
  245.  
  246. #if STRING_FORMAL
  247. stparmscan(delim, dp)
  248. int        delim;
  249. register DEFBUF    *dp;
  250. /*
  251.  * Scan the string (starting with the given delimiter).
  252.  * The token is replaced if it is the only text in this string or
  253.  * character constant.  The algorithm follows checkparm() above.
  254.  * Note that scanstring() has approved of the string.
  255.  */
  256. {
  257.     register int        c;
  258.  
  259.     /*
  260.      * Warning -- this code hasn't been tested for a while.
  261.      * It exists only to preserve compatibility with earlier
  262.      * implementations of cpp.  It is not part of the Draft
  263.      * ANSI Standard C language.
  264.      */
  265.     save(delim);
  266.     instring = TRUE;
  267.     while ((c = get()) != delim
  268.          && c != '\n'
  269.          && c != EOF_CHAR) {
  270.         if (type[c] == LET)            /* Maybe formal parm    */
  271.         checkparm(c, dp);
  272.         else {
  273.         save(c);
  274.         if (c == '\\')
  275.             save(get());
  276.         }
  277.     }
  278.     instring = FALSE;
  279.     if (c != delim)
  280.         cerror("Unterminated string in macro body", NULLST);
  281.     save(c);
  282. }
  283. #endif
  284.  
  285. doundef()
  286. /*
  287.  * Remove the symbol from the defined list.
  288.  * Called from the #control processor.
  289.  */
  290. {
  291.   register int c;
  292.  
  293.   if (type[(c = skipws())] != LET)
  294.     cerror("Illegal #undef argument", NULLST);
  295.   else
  296.     {
  297.       scanid(c);                /* Get name to tokenbuf */
  298.       defendel(tokenbuf, TRUE);
  299.     }
  300. }
  301.  
  302. textput(text)
  303. char        *text;
  304. /*
  305.  * Put the string in the parm[] buffer.
  306.  */
  307. {
  308.     register int    size;
  309.  
  310.     size = strlen(text) + 1;
  311.     if ((parmp + size) >= &parm[NPARMWORK])
  312.         cfatal("Macro work area overflow", NULLST);
  313.     else {
  314.         strcpy(parmp, text);
  315.         parmp += size;
  316.     }
  317. }
  318.  
  319. charput(c)
  320. register int    c;
  321. /*
  322.  * Put the byte in the parm[] buffer.
  323.  */
  324. {
  325.     if (parmp >= &parm[NPARMWORK])
  326.         cfatal("Macro work area overflow", NULLST);
  327.     else {
  328.         *parmp++ = c;
  329.     }
  330. }
  331.  
  332. /*
  333.  *        M a c r o   E x p a n s i o n
  334.  */
  335.  
  336. expand(tokenp)
  337. register DEFBUF    *tokenp;
  338. /*
  339.  * Expand a macro.  Called from the cpp mainline routine (via subroutine
  340.  * macroid()) when a token is found in the symbol table.  It calls
  341.  * expcollect() to parse actual parameters, checking for the correct number.
  342.  * It then creates a "file" containing a single line containing the
  343.  * macro with actual parameters inserted appropriately.  This is
  344.  * "pushed back" onto the input stream.  (When the get() routine runs
  345.  * off the end of the macro line, it will dismiss the macro itself.)
  346.  */
  347. {
  348.     register int        c;
  349.  
  350. #if DEBUG
  351.     if (debug)
  352.         dumpadef("expand entry", tokenp);
  353. #endif    
  354.     /*
  355.      * If no macro is pending, save the name of this macro
  356.      * for an eventual error message.
  357.      */
  358.     if (recursion++ == 0)
  359.         macro = tokenp;
  360.     else if (recursion == RECURSION_LIMIT) {
  361.         cerror("Recursive macro definition of \"%s\"", tokenp->name);
  362.         fprintf(stderr, "(Defined by \"%s\")\n", macro->name);
  363.         if (rec_recover) {
  364.         do {
  365.             c = get();
  366.         } while (infile != NULL && infile->fp == NULL);
  367.         unget();
  368.         recursion = 0;
  369.         return;
  370.         }
  371.     }
  372.     /*
  373.      * Here's a macro to expand.
  374.      */
  375.     nargs = 0;                /* Formals counter    */
  376.     parmp = parm;                /* Setup parm buffer    */
  377.     switch (tokenp->nargs) {
  378.     case DEF_BUILTIN:
  379.       (tokenp->expander)(tokenp->repl);    /* Builtin  macros      */
  380.       break;
  381.     default:
  382.         /*
  383.          * Nothing funny about this macro.
  384.          */
  385.         if (tokenp->nargs < 0)
  386.         cfatal("Bug: Illegal __ macro \"%s\"", tokenp->name);
  387.         while ((c = skipws()) == '\n')    /* Look for (, skipping    */
  388.         wrongline = TRUE;        /* spaces and newlines    */
  389.         if (c != '(') {
  390.         /*
  391.          * If the programmer writes
  392.          *    #define foo() ...
  393.          *    ...
  394.          *    foo [no ()]
  395.          * just write foo to the output stream.
  396.          */
  397.         unget();
  398.         cwarn("Macro \"%s\" needs arguments", tokenp->name);
  399.         fputs(tokenp->name, stdout);
  400.         return;
  401.         }
  402.         else if (expcollect()) {        /* Collect arguments    */
  403.         if (tokenp->nargs != nargs) {    /* Should be an error?    */
  404.             cwarn("Wrong number of macro arguments for \"%s\"",
  405.             tokenp->name);
  406.         }
  407. #if DEBUG
  408.         if (debug)
  409.             dumpparm("expand");
  410. #endif
  411.         }                /* Collect arguments        */
  412.     case DEF_NOARGS:        /* No parameters just stuffs    */
  413.         expstuff(tokenp);        /* Do actual parameters        */
  414.     }                /* nargs switch            */
  415. }
  416.  
  417. void
  418. expand_line (dp)
  419.   char* dp;
  420. {
  421.   sprintf(work, "%d", line);
  422.   ungetstring(work);
  423. }
  424.  
  425. void
  426. expand_file (dp)
  427.      char *dp;
  428. {
  429.   register FILEINFO    *file;
  430.               /* Find bottom level file (the file being compiled) */
  431.   for (file = infile; file != NULL; file = file->parent) {
  432.     if (file->parent == NULL) {
  433.       sprintf(work, "\"%s\"", (file->progname != NULL)
  434.           ? file->progname : file->filename);
  435.       ungetstring(work);
  436.       break;
  437.     }
  438.   }
  439. }
  440.  
  441. #ifndef COOL
  442. /* We need this routine here only when we are building a clean, ie. non-COOL
  443.  * preprocessor. For COOL, this function is defined in cpp7.c
  444.  */
  445. FILEINFO*
  446. get_temp_file (bufsize, name)
  447.      int bufsize;
  448.      char* name;
  449. {
  450.   extern FILEINFO    *getfile();
  451.   FILEINFO* file = getfile(bufsize, name);
  452.   infile = file->parent;
  453.   file->parent = NULL;
  454.   line = infile->line;
  455.   return(file);
  456. }
  457. #endif
  458.  
  459. FILE_LOCAL int
  460. expcollect()
  461. /*
  462.  * Collect the actual parameters for this macro.  TRUE if ok.
  463.  */
  464. {
  465.     register int    c;
  466.     register int    paren;            /* For embedded ()'s    */
  467.     extern int    charput();
  468.  
  469.     for (;;) {
  470.         paren = 0;                /* Collect next arg.    */
  471.         while ((c = skipws()) == '\n')    /* Skip over whitespace    */
  472.         wrongline = TRUE;        /* and newlines.    */
  473.         if (c == ')') {            /* At end of all args?    */
  474.         /*
  475.          * Note that there is a guard byte in parm[]
  476.          * so we don't have to check for overflow here.
  477.          */
  478.         *parmp = EOS;            /* Make sure terminated    */
  479.         break;                /* Exit collection loop    */
  480.         }
  481.         else if (nargs >= LASTPARM)
  482.         cfatal("Too many arguments in macro expansion", NULLST);
  483.         parlist[nargs++] = parmp;        /* At start of new arg    */
  484.         for (;; c = cget()) {        /* Collect arg's bytes    */
  485.         if (c == EOF_CHAR) {
  486.             cfatal("end of file within macro argument", NULLST);
  487.             return (FALSE);        /* Sorry.        */
  488.         }
  489.         else if (c == '\\') {        /* Quote next character    */
  490.             charput(c);            /* Save the \ for later    */
  491.             charput(cget());        /* Save the next char.    */
  492.             continue;            /* And go get another    */
  493.         }
  494.         else if (type[c] == QUO) {    /* Start of string?    */
  495.             scanstring(c, charput);    /* Scan it off        */
  496.             continue;            /* Go get next char    */
  497.         }
  498.         else if (c == '(')        /* Worry about balance    */
  499.             paren++;            /* To know about commas    */
  500.         else if (c == ')') {        /* Other side too    */
  501.             if (paren == 0) {        /* At the end?        */
  502.             unget();        /* Look at it later    */
  503.             break;            /* Exit arg getter.    */
  504.             }
  505.             paren--;            /* More to come.    */
  506.         }
  507.         else if (c == ',' && paren == 0) /* Comma delimits args    */
  508.             break;
  509.         else if (c == '\n')        /* Newline inside arg?    */
  510.             wrongline = TRUE;        /* We'll need a #line    */
  511.         charput(c);            /* Store this one    */
  512.         }                    /* Collect an argument    */
  513.         charput(EOS);            /* Terminate argument    */
  514. #if DEBUG
  515.         if (debug)
  516.             printf("parm[%d] = \"%s\"\n", nargs, parlist[nargs - 1]);
  517. #endif
  518.     }                    /* Collect all args.    */
  519.     return (TRUE);                /* Normal return    */
  520. }
  521.  
  522. FILE_LOCAL
  523. expstuff(tokenp)
  524. DEFBUF        *tokenp;        /* Current macro being expanded    */
  525. /*
  526.  * Stuff the macro body, replacing formal parameters by actual parameters.
  527.  */
  528. {
  529.     register int    c;            /* Current character    */
  530.     register char    *inp;            /* -> repl string    */
  531.     register char    *defp;            /* -> macro output buff    */
  532.     int        size;            /* Actual parm. size    */
  533.     char        *defend;        /* -> output buff end    */
  534.     int        string_magic;        /* String formal hack    */
  535.     FILEINFO    *file;                /* Funny #include    */
  536.     extern FILEINFO    *getfile();
  537.     extern FILEINFO    *get_temp_file();
  538.  
  539.     file = getfile(NBUFF, tokenp->name);
  540.     inp = tokenp->repl;            /* -> macro replacement    */
  541.     defp = file->buffer;            /* -> output buffer    */
  542.     defend = defp + (NBUFF - 24);        /* Note its end        */
  543.     if (inp != NULL) {
  544.         while ((c = (*inp++ & 0xFF)) != EOS) {
  545.           if (defp >= defend) {        /* If out of space      */
  546.         FILEINFO* new = get_temp_file(NBUFF, file->filename);
  547.         new->parent = file->parent; /* When new ends read from infile */
  548.         file->parent = new;        /* When file ends read from new   */
  549.         file = new;
  550.         *defp = EOS;
  551.         defp = file->buffer;
  552.         defend = defp + (NBUFF - 24);
  553.           }
  554.  
  555.           if (c >= MAC_PARM && c <= (MAC_PARM + PAR_MAC)) {
  556.         string_magic = (c == (MAC_PARM + PAR_MAC));
  557.         if (string_magic) {        /* When quoted parameter */
  558.           c = (*inp++ & 0xFF);
  559.           *defp++ = '\"';
  560.         }
  561.         /*
  562.          * Replace formal parameter by actual parameter string.
  563.          */
  564.         if ((c -= MAC_PARM) < nargs) {
  565.           size = strlen(parlist[c]);
  566.           if ((defp + size + 24) >= defend) {
  567.             *defp = EOS;        /* If out of space */
  568.             defend = defp;
  569.             if (string_magic) inp--; 
  570.             inp--;            /* backup and try again */
  571.             continue;
  572.           }
  573.           if (string_magic) {        /* When quoted parameter */
  574.             char* p = parlist[c];
  575.             for(; (c = *p++) != EOS;) {
  576.               switch (c) {
  577.               case '\"':
  578.               case '\\':
  579.             *defp++ = '\\';
  580.               default:
  581.             *defp++ = c;
  582.               } /* switch */
  583.             } /* for */
  584.             *defp++ = '\"';
  585.           } else {
  586.             strncpy(defp, parlist[c], size);
  587.             defp += size;
  588.           } /* if string_magic */
  589.         } /* if valid parm */
  590.           } /* if parm */
  591.           else
  592.         *defp++ = c;
  593.         }
  594.       }
  595.     *defp = EOS;
  596. #if DEBUG
  597.     if (debug > 1)
  598.         printf("macroline: \"%s\"\n", file->buffer);
  599. #endif
  600. }
  601.  
  602. #if DEBUG
  603. dumpparm(why)
  604. char        *why;
  605. /*
  606.  * Dump parameter list.
  607.  */
  608. {
  609.     register int    i;
  610.  
  611.     printf("dump of %d parameters (%d bytes total) %s\n",
  612.         nargs, parmp - parm, why);
  613.     for (i = 0; i < nargs; i++) {
  614.         printf("parm[%d] (%d) = \"%s\"\n",
  615.         i + 1, strlen(parlist[i]), parlist[i]);
  616.     }
  617. }
  618. #endif
  619.